/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.zyyoona7.picker;

import com.zyyoona7.picker.util.AttrUtil;
import ohos.agp.components.AttrSet;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.TextField;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Picker;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;
import java.util.Calendar;

/**
 * 自定义DatePicker样例
 *
 * @author gc
 * @since 2021-04-13
 */
public class DatePickerViewEx extends DirectionalLayout implements Component.DrawTask {

    private Picker mYear;
    private Picker mMonth;
    private Picker mDay;

    private TextField mYearText;
    private TextField mMonthText;
    private TextField mDayText;

    private boolean isDisplayYear = true;
    private boolean isDisplayMonth = true;
    private boolean isDisplayDay = true;
    private boolean isFormatNum = false;
    private boolean isAppendText = false;
    private boolean isWheelModeEnabled = false;
    private boolean isDisplayText = false;
    private boolean isDisplayLine = false;
    private boolean isAllLine = true;
    private boolean isDisplayBg = false;

    private Color mSelectedColorYear = Color.BLACK;
    private Color mSelectedColorMonth = Color.BLACK;
    private Color mSelectedColorDay = Color.BLACK;
    private Color mNormalColorYear = Color.BLACK;
    private Color mNormalColorMonth = Color.BLACK;
    private Color mNormalColorDay = Color.BLACK;

    private int mSpacing;

    private static final float alpha = 0.15f;

    private static final int num2 = 2;
    private static final int num4 = 4;
    private static final int num6 = 6;
    private static final int num9 = 9;
    private static final int num10 = 10;
    private static final int num11 = 11;
    private static final int num28 = 28;
    private static final int num29 = 29;
    private static final int num30 = 30;
    private static final int num31 = 31;
    private static final int num100 = 100;
    private static final int num400 = 400;

    private ValueChangeListener mValueChangeListener;

    /**
     * 构造方法
     *
     * @param context
     */
    public DatePickerViewEx(Context context) {
        super(context);
        init(context);
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrSet
     */
    public DatePickerViewEx(Context context, AttrSet attrSet) {
        super(context, attrSet);
        initAttr(attrSet);
        init(context);
    }

    /**
     * 构造方法
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public DatePickerViewEx(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initAttr(attrSet);
        init(context);
    }

    /**
     * setValueChangeListener
     *
     * @param valueChangeListener
     */
    public void setValueChangeListener(ValueChangeListener valueChangeListener) {
        mValueChangeListener = valueChangeListener;
    }

    private void initAttr(AttrSet attrSet) {
        isDisplayYear = AttrUtil.getBooleanValue(attrSet, "is_display_year", true);
        isDisplayMonth = AttrUtil.getBooleanValue(attrSet, "is_display_month", true);
        isDisplayDay = AttrUtil.getBooleanValue(attrSet, "is_display_day", true);
        isDisplayText = AttrUtil.getBooleanValue(attrSet, "is_display_text", false);
        isWheelModeEnabled = AttrUtil.getBooleanValue(attrSet, "wheel_mode_enabled", false);
        isFormatNum = AttrUtil.getBooleanValue(attrSet, "is_format_num", false);
        isAppendText = AttrUtil.getBooleanValue(attrSet, "is_append_text", false);
        isDisplayLine = AttrUtil.getBooleanValue(attrSet, "is_display_line", false);
        isAllLine = AttrUtil.getBooleanValue(attrSet, "is_all_line", true);
        isDisplayBg = AttrUtil.getBooleanValue(attrSet, "is_display_bg", false);
        String defaultSelectedColor = "#000000";
        mSelectedColorYear = AttrUtil.getColorValue(attrSet, "selected_text_color_year", defaultSelectedColor);
        mSelectedColorMonth = AttrUtil.getColorValue(attrSet, "selected_text_color_month", defaultSelectedColor);
        mSelectedColorDay = AttrUtil.getColorValue(attrSet, "selected_text_color_day", defaultSelectedColor);
        String defaultNormalColor = "#888888";
        mNormalColorYear = AttrUtil.getColorValue(attrSet, "normal_text_color_year", defaultNormalColor);
        mNormalColorMonth = AttrUtil.getColorValue(attrSet, "normal_text_color_month", defaultNormalColor);
        mNormalColorDay = AttrUtil.getColorValue(attrSet, "normal_text_color_day", defaultNormalColor);
        mSpacing = AttrUtil.getIntegerValue(attrSet, "spacing", 0);
    }

    private void init(Context context) {
        initView(context);
        initPicker(context);
        initCurrentDate();
    }

    private void initCurrentDate() {
        Calendar calendar = Calendar.getInstance(); // 获取calendar(日历)对象
        int currentYear = calendar.get(Calendar.YEAR); // 年
        int currentMonth = calendar.get(Calendar.MONTH) + 1; // 月
        int currentDay = calendar.get(Calendar.DAY_OF_MONTH); // 日

        mYear.setValue(currentYear);
        mMonth.setValue(currentMonth);
        mDay.setValue(currentDay);
    }

    private void setPickerDisplay(Picker picker, boolean isDisplay) {
        picker.setVisibility(isDisplay ? VISIBLE : HIDE);
    }

    private void setPickTextColor(Picker picker, Color selectedColor, Color normalColor) {
        picker.setSelectedTextColor(selectedColor);
        picker.setNormalTextColor(normalColor);
    }

    private void setLineElement(Context context) {
        ShapeElement line = new ShapeElement(context, ResourceTable.Layout_shape_line);
        mYear.setDisplayedLinesTopElement(line);
        mMonth.setDisplayedLinesTopElement(line);
        mDay.setDisplayedLinesTopElement(line);
        mYear.setDisplayedLinesBottomElement(line);
        mMonth.setDisplayedLinesBottomElement(line);
        mDay.setDisplayedLinesBottomElement(line);
    }

    private void setWheelModeEnabled() {
        mYear.setWheelModeEnabled(isWheelModeEnabled);
        mMonth.setWheelModeEnabled(isWheelModeEnabled);
        mDay.setWheelModeEnabled(isWheelModeEnabled);
    }

    /**
     * onDraw
     *
     * @param component
     * @param canvas
     */
    @Override
    public void onDraw(Component component, Canvas canvas) {
        Paint paint = new Paint();
        int height = component.getHeight() / ((Picker)component).getSelectorItemNum();
        int start = ((Picker)component).getSelectorItemNum() / num2 * height;
        paint.setColor(Color.GRAY);
        paint.setAlpha(alpha);
        canvas.drawRect(0,start,component.getWidth(),start + height, paint);
    }

    private void setDisplayBg() {
        if (isDisplayBg) {
            mYear.addDrawTask(this);
            mMonth.addDrawTask(this);
            mDay.addDrawTask(this);
        }
    }

    private void initPicker(Context context) {
        setFormatForText(mYear, isAppendText ? "年" : "");
        setFormatForText(mMonth, isAppendText ? "月" : "");
        setFormatForText(mDay, isAppendText ? "日" : "");

        setTextDisplay(isDisplayText);

        setPickerDisplay(mYear, isDisplayYear);
        setPickerDisplay(mMonth, isDisplayMonth);
        setPickerDisplay(mDay, isDisplayDay);

        // 设置选中颜色
        setPickTextColor(mYear, mSelectedColorYear, mNormalColorYear);
        setPickTextColor(mMonth, mSelectedColorMonth, mNormalColorMonth);
        setPickTextColor(mDay, mSelectedColorDay, mNormalColorDay);

        // 设置是否可以循环显示
        setWheelModeEnabled();

        // 设置线
        if (isDisplayLine) {
            setLineElement(context);
        }

        mYear.setValueChangedListener(new Picker.ValueChangedListener() {
            @Override
            public void onValueChanged(Picker picker, int index, int value) {
                mDay.setMaxValue(getMaxDay(value, mMonth.getValue()));
                notifyValueChangeListener();
            }
        });

        mMonth.setValueChangedListener(new Picker.ValueChangedListener() {
            @Override
            public void onValueChanged(Picker picker, int index, int value) {
                mDay.setMaxValue(getMaxDay(mYear.getValue(), value));
                notifyValueChangeListener();
            }
        });

        mDay.setValueChangedListener(new Picker.ValueChangedListener() {
            @Override
            public void onValueChanged(Picker picker, int index, int value) {
                notifyValueChangeListener();
            }
        });

        if (!isAllLine) {
            setAllLine();
        }

        setSpacing();

        setDisplayBg();
    }

    private void notifyValueChangeListener() {
        if (mValueChangeListener != null) {
            mValueChangeListener.onValueChange();
        }
    }

    private void setSpacing() {
        mYear.setPadding(mSpacing, 0, mSpacing, 0);
        mMonth.setPadding(mSpacing, 0, mSpacing, 0);
        mDay.setPadding(mSpacing, 0, mSpacing, 0);
    }

    private void setAllLine() {
        mYear.setWidth(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        mMonth.setWidth(ComponentContainer.LayoutConfig.MATCH_CONTENT);
        mDay.setWidth(ComponentContainer.LayoutConfig.MATCH_CONTENT);
    }

    private void initView(Context context) {
        Component component = LayoutScatter.getInstance(context)
                .parse(ResourceTable.Layout_layout_date_picker_view_ex, this, false);

        mYear = (Picker) component.findComponentById(ResourceTable.Id_year);
        mMonth = (Picker) component.findComponentById(ResourceTable.Id_month);
        mDay = (Picker) component.findComponentById(ResourceTable.Id_day);

        mYearText = (TextField) component.findComponentById(ResourceTable.Id_year_text);
        mMonthText = (TextField) component.findComponentById(ResourceTable.Id_month_text);
        mDayText = (TextField) component.findComponentById(ResourceTable.Id_day_text);

        this.addComponent(component);
    }

    private void setFormatForText(Picker picker, final String text) {
        picker.setFormatter(new Picker.Formatter() {
            @Override
            public String format(int value) {
                String data = null;
                if (isFormatNum) {
                    if (value < num10) {
                        data = "0" + value + text;
                    } else {
                        data = value + text;
                    }
                } else {
                    data = value + text;
                }

                return " " + data + " ";
            }
        });
    }

    /**
     * 获得当前月份的天数
     *
     * @param year 年份
     * @param month 月份
     * @return 获取当前年月所对应日期的最大天数
     */
    public int getMaxDay(final int year, int month) {
        switch(month) {
            case num2:
                int flagF = year % num400;
                int flagS = year % num4;
                int flagT = year % num100;
                return flagF == 0 || (flagS == 0 && flagT != 0) ? num29 : num28;
            case num4: case num6: case num9: case num11: return num30;
            default: return num31;
        }
    }

    /**
     * 获取当前年
     *
     * @return 当前年
     */
    public String getYear() {
        if (!isDisplayYear) {
            return "";
        }
        return mYear.getValue() + "";
    }

    /**
     * 获取当前月
     *
     * @return 当前月
     */
    public String getMonth() {
        if (!isDisplayMonth) {
            return "";
        }
        return mMonth.getValue() + "";
    }

    /**
     * 获取当前年
     *
     * @return 当前年
     */
    public String getDay() {
        if (!isDisplayDay) {
            return "";
        }
        return mDay.getValue() + "";
    }

    /**
     * 设置是否显示年
     *
     * @param isDisplay
     */
    public void setYearDisplay(boolean isDisplay) {
        mYear.setVisibility(isDisplay ? VISIBLE : HIDE);
    }

    /**
     * 设置是否显示月
     *
     * @param isDisplay
     */
    public void setMonthDisplay(boolean isDisplay) {
        mYear.setVisibility(isDisplay ? VISIBLE : HIDE);
    }

    /**
     * 设置是否显示日
     *
     * @param isDisplay
     */
    public void setDayDisplay(boolean isDisplay) {
        mYear.setVisibility(isDisplay ? VISIBLE : HIDE);
    }

    /**
     * 设置是否显汉子年，月，日
     *
     * @param isDisplay
     */
    public void setTextDisplay(boolean isDisplay) {
        mYearText.setVisibility(isDisplay && isDisplayYear ? VISIBLE : HIDE);
        mMonthText.setVisibility(isDisplay && isDisplayMonth ? VISIBLE : HIDE);
        mDayText.setVisibility(isDisplay && isDisplayDay ? VISIBLE : HIDE);
    }

    /**
     * 设置当前年份
     *
     * @param year
     */
    public void setYear(int year) {
        if (year < mYear.getMinValue() || year > mYear.getMaxValue()) {
            return;
        }
        mYear.setValue(year);
    }

    /**
     * 设置当前月份
     *
     * @param month
     */
    public void setMonth(int month) {
        if (month < mMonth.getMinValue() || month > mMonth.getMaxValue()) {
            return;
        }
        mMonth.setValue(month);
    }

    /**
     * 设置当前日
     *
     * @param day
     */
    public void setDay(int day) {
        if (day < mDay.getMinValue() || day > mDay.getMaxValue()) {
            return;
        }
        mDay.setValue(day);
    }

    /**
     * 自定义监听
     *
     * @author gc
     * @since 2021-04-13
     */
    public interface ValueChangeListener {
        /** 值改变监听 */
        void onValueChange();
    }
}
